//
//  TouchDrawView.m
//  touch-demo
//
//  Created by holyen on 12-10-10.
//  Copyright (c) 2012年 holyen. All rights reserved.
//

#import "TouchDrawView.h"
#import "Line.h"
#import "FileHelpers.h"
#import <QuartzCore/QuartzCore.h>

@implementation TouchDrawView

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self)
    {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(termin:) name:UIApplicationDidEnterBackgroundNotification object:nil];
        [self fetchLinesIfNecessary];
        [self setMultipleTouchEnabled:YES];//多点触摸
        [self setNeedsDisplay];
    }
    return self;
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [_linesInProcess release];
    [_completeLines release];
    [super dealloc];
}

- (void)termin:(NSNotification *)note
{
    NSLog(@"进入后台!!!");
    [self saveChanges];
}

//Block 语法: UIColor * 表示为返回的类型, (^) 表示定义Block对象的特定符号 (Line *) 表示传入的参数
- (void)transformLineColorsWithBlock:(UIColor * (^)(Line *))colorForLine
{
    //    for (Line *l in _completeLines)
    //    {
    //        UIColor *c = colorForLine(l);
    //        [l setColor:c];
    //    }
    
    //上面的方法使用下面这句代替:

    [_completeLines enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
    {
        [(Line *)obj setColor:colorForLine(obj)]; //arrayEnmuerBlock(obj,idx,stop);
        
    }
    ];
    //    void (^arrayEnmuerBlock)(id obj,NSUInteger idx, BOOL *stop) = ^(id obj,NSUInteger idx, BOOL *stop)
    //    {
    //        [(Line *)obj setColor:colorForLine(obj)];
    //    };
    
    [self setNeedsDisplay];
}

- (void)colorSize
{
    //越是垂直越红,越是水平越绿
    //越长越蓝
    
    //创建名为colorScheme 的Block 对象变量:
    UIColor * (^colorScheme)(Line *) = ^(Line *l)
    {
        float dx = [l end].x - [l begin].x;
        float dy = [l end].y - [l begin].y;
        
        float r = (fabs(dx) < 0.001 ? 1.0 : fabs(dy/dx));
        float g = (fabs(dy) < 0.001 ? 1.0 : fabs(dx/dy));
        float b = hypot(dx, dy) / 300.0;
        
        return [UIColor colorWithRed:r green:g blue:b alpha:1];
    };
    
    [self transformLineColorsWithBlock:colorScheme];
}

- (BOOL)canBecomeFirstResponder
{
    return YES;
}

- (void)didMoveToWindow
{
    [self becomeFirstResponder];
}

- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
    [self colorSize];
}

-(void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(context, 10.0);
    CGContextSetLineCap(context, kCGLineCapRound);
    
    //
    //[[UIColor blackColor] set];
    for (Line *line in _completeLines)
    {
        [[line color] set];
        
        CGContextMoveToPoint(context, [line begin].x, [line begin].y);
        CGContextAddLineToPoint(context, [line end].x, [line end].y);
        CGContextStrokePath(context);
    }
    
    [[UIColor redColor] set];
    for (NSValue *v in _linesInProcess)
    {
        Line *line = [_linesInProcess objectForKey:v];
        CGContextMoveToPoint(context, [line begin].x, [line begin].y);
        CGContextAddLineToPoint(context, [line end].x, [line end].y);
        CGContextStrokePath(context);
    }
    NSLog(@"-drawRect:");
}

- (void)clearAll
{
    //创建新层:
    CALayer *fadeLayer = [CALayer layer];
    [fadeLayer setBounds:[self bounds]];
    [fadeLayer setPosition:CGPointMake([self bounds].size.width / 2.0, [self bounds].size.height / 2.0)];
    [fadeLayer setBackgroundColor:[[self backgroundColor] CGColor]];
    
    //将新建的层加入层的心层次结构并位于视图的隐式层之上
    [[self layer] addSublayer:fadeLayer];
    //为该层创建淡入动画,设置持续时间为1秒
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    [animation setDelegate:self];
    [animation setFromValue:[NSNumber numberWithFloat:0]];
    [animation setToValue:[NSNumber numberWithFloat:1.0]];
    [animation setDuration:1];
    [fadeLayer addAnimation:animation forKey:@"fade"];
    
    [CATransaction begin];
    [CATransaction setCompletionBlock:^(void)
     {
         [fadeLayer removeFromSuperlayer];
         [_linesInProcess removeAllObjects];
         [_completeLines removeAllObjects];
         [self setNeedsDisplay];
     }
     ];
    [CATransaction commit];
}

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
    
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    for (UITouch *t in touches)
    {
        //是否连接:
        if ([t tapCount] > 1) {
            [self clearAll];
            return;
        }
        
        //将封装在NSValue 对象中的触摸对象当成键来使用
        NSValue *key = [NSValue valueWithPointer:t];//指针当作key使用
        //根据触摸位置创建line对象
        CGPoint loc = [t locationInView:self];
        Line *newLine = [[Line alloc] init];
        [newLine setBegin:loc];
        [newLine setEnd:loc];
        
        //通过相应的键,将Line对象加入NSMutableDictionary对象
        [_linesInProcess setObject:newLine forKey:key];
        //!内存 泄漏
    }
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    for (UITouch *t in touches)
    {
        NSValue *key = [NSValue valueWithPointer:t];
        //找出和该触摸相对应的Line对象
        Line *line = [_linesInProcess objectForKey:key];
        
        CGPoint loc = [t locationInView:self];
        [line setEnd:loc];
    }
    [self setNeedsDisplay];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self endTouches:touches];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self endTouches:touches];    
}

- (void)endTouches:(NSSet *)touches
{
    //删除NSMutableDictionary 对象中已完成的Line 对象
    for (UITouch *t in touches)
    {
        NSValue *key = [NSValue valueWithPointer:t];
        Line *line = [_linesInProcess objectForKey:key];
        
        if (line) {
            [_completeLines addObject:line];
            [_linesInProcess removeObjectForKey:key];
        }
    }
    
    [self setNeedsDisplay];
}

- (BOOL)saveChanges
{
    [self fetchLinesIfNecessary];
    return [NSKeyedArchiver archiveRootObject:_completeLines toFile:[self linesOfCompleteArchivePath]];
}

- (void)fetchLinesIfNecessary
{
    if (!_completeLines) {
        NSString *path = [self linesOfCompleteArchivePath];
        _completeLines = [[NSKeyedUnarchiver unarchiveObjectWithFile:path] retain];
    }
    if (!_completeLines) {
        _completeLines = [[NSMutableArray alloc] init];
    }
    if (!_linesInProcess) {
        _linesInProcess = [[NSMutableDictionary alloc] init];
    }
}

- (NSString *)linesOfCompleteArchivePath
{
    return pathInDocumentDirectory(@"linesOfComplete.data");
}

@end
